<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Simplified Hibernate ORM with Panache</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/hibernate-orm-panache" />
  <meta property="og:title" content="Quarkus - Simplified Hibernate ORM with Panache" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/hibernate-orm-panache">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Simplified Hibernate ORM with Panache</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#first-an-example">First: an example</a></li>
<li><a href="#solution">Solution</a></li>
<li><a href="#setting-up-and-configuring-hibernate-orm-with-panache">Setting up and configuring Hibernate ORM with Panache</a></li>
<li><a href="#solution-1-using-the-active-record-pattern">Solution 1: using the active record pattern</a>
<ul class="sectlevel2">
<li><a href="#defining-your-entity">Defining your entity</a></li>
<li><a href="#most-useful-operations">Most useful operations</a></li>
<li><a href="#adding-entity-methods">Adding entity methods</a></li>
</ul>
</li>
<li><a href="#solution-2-using-the-repository-pattern">Solution 2: using the repository pattern</a>
<ul class="sectlevel2">
<li><a href="#defining-your-entity-2">Defining your entity</a></li>
<li><a href="#defining-your-repository">Defining your repository</a></li>
<li><a href="#most-useful-operations-2">Most useful operations</a></li>
</ul>
</li>
<li><a href="#advanced-query">Advanced Query</a>
<ul class="sectlevel2">
<li><a href="#paging">Paging</a></li>
<li><a href="#using-a-range-instead-of-pages">Using a range instead of pages</a></li>
<li><a href="#sorting">Sorting</a></li>
<li><a href="#simplified-queries">Simplified queries</a></li>
<li><a href="#named-queries">Named queries</a></li>
<li><a href="#query-parameters">Query parameters</a></li>
<li><a href="#query-projection">Query projection</a></li>
</ul>
</li>
<li><a href="#transactions">Transactions</a></li>
<li><a href="#lock-management">Lock management</a>
<ul class="sectlevel2">
<li><a href="#first-locking-using-findbyid">First: Locking using findById().</a></li>
<li><a href="#second-locking-in-a-find">Second: Locking in a find().</a></li>
</ul>
</li>
<li><a href="#custom-ids">Custom IDs</a></li>
<li><a href="#mocking">Mocking</a>
<ul class="sectlevel2">
<li><a href="#using-the-active-record-pattern">Using the active record pattern</a></li>
<li><a href="#using-the-repository-pattern">Using the repository pattern</a></li>
</ul>
</li>
<li><a href="#how-and-why-we-simplify-hibernate-orm-mappings">How and why we simplify Hibernate ORM mappings</a></li>
<li><a href="#defining-entities-in-external-projects-or-jars">Defining entities in external projects or jars</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Hibernate ORM is the de facto JPA implementation and offers you the full breadth of an Object Relational Mapper.
It makes complex mappings possible, but it does not make simple and common mappings trivial.
Hibernate ORM with Panache focuses on making your entities trivial and fun to write in Quarkus.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="first-an-example"><a class="anchor" href="#first-an-example"></a>First: an example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>What we&#8217;re doing in Panache is allow you to write your Hibernate ORM entities like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person extends PanacheEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    public static Person findByName(String name){
        return find("name", name).firstResult();
    }

    public static List&lt;Person&gt; findAlive(){
        return list("status", Status.Alive);
    }

    public static void deleteStefs(){
        delete("name", "Stef");
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You have noticed how much more compact and readable the code is?
Does this look interesting? Read on!</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
the <code>list()</code> method might be surprising at first. It takes fragments of HQL (JP-QL) queries and contextualizes the rest. That makes for very concise but yet readable code.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
what was described above is essentially the <a href="https://www.martinfowler.com/eaaCatalog/activeRecord.html">active record pattern</a>, sometimes just called the entity pattern.
Hibernate with Panache also allows for the use of the more classical <a href="https://martinfowler.com/eaaCatalog/repository.html">repository pattern</a> via <code>PanacheRepository</code>.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution"><a class="anchor" href="#solution"></a>Solution</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.</p>
</div>
<div class="paragraph">
<p>Clone the Git repository: <code>git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a></code>, or download an <a href="https://github.com/quarkusio/quarkus-quickstarts/archive/master.zip">archive</a>.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>hibernate-orm-panache-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/hibernate-orm-panache-quickstart">directory</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="setting-up-and-configuring-hibernate-orm-with-panache"><a class="anchor" href="#setting-up-and-configuring-hibernate-orm-with-panache"></a>Setting up and configuring Hibernate ORM with Panache</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To get started:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>add your settings in <code>application.properties</code></p>
</li>
<li>
<p>annotate your entities with <code>@Entity</code></p>
</li>
<li>
<p>make your entities extend <code>PanacheEntity</code> (optional if you are using the repository pattern)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Follow the <a href="hibernate-orm#setting-up-and-configuring-hibernate-orm">Hibernate set-up guide for all configuration</a>.</p>
</div>
<div class="paragraph">
<p>In your <code>pom.xml</code>, add the following dependencies:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the Panache JPA extension</p>
</li>
<li>
<p>your JDBC driver extension (<code>quarkus-jdbc-postgresql</code>, <code>quarkus-jdbc-h2</code>, <code>quarkus-jdbc-mariadb</code>, &#8230;&#8203;)</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependencies&gt;
    &lt;!-- Hibernate ORM specific dependencies --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
        &lt;artifactId&gt;quarkus-hibernate-orm-panache&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;!-- JDBC driver dependencies --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
        &lt;artifactId&gt;quarkus-jdbc-postgresql&lt;/artifactId&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then add the relevant configuration properties in <code>application.properties</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs"># configure your datasource
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = sarah
quarkus.datasource.password = connor
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation = drop-and-create</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution-1-using-the-active-record-pattern"><a class="anchor" href="#solution-1-using-the-active-record-pattern"></a>Solution 1: using the active record pattern</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="defining-your-entity"><a class="anchor" href="#defining-your-entity"></a>Defining your entity</h3>
<div class="paragraph">
<p>To define a Panache entity, simply extend <code>PanacheEntity</code>, annotate it with <code>@Entity</code> and add your
columns as public fields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person extends PanacheEntity {
    public String name;
    public LocalDate birth;
    public Status status;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can put all your JPA column annotations on the public fields. If you need a field to not be persisted, use the
<code>@Transient</code> annotation on it. If you need to write accessors, you can:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person extends PanacheEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    // return name as uppercase in the model
    public String getName(){
        return name.toUpperCase();
    }

    // store all names in lowercase in the DB
    public void setName(String name){
        this.name = name.toLowerCase();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And thanks to our field access rewrite, when your users read <code>person.name</code> they will actually call your <code>getName()</code> accessor,
and similarly for field writes and the setter.
This allows for proper encapsulation at runtime as all fields calls will be replaced by the corresponding getter/setter calls.</p>
</div>
</div>
<div class="sect2">
<h3 id="most-useful-operations"><a class="anchor" href="#most-useful-operations"></a>Most useful operations</h3>
<div class="paragraph">
<p>Once you have written your entity, here are the most common operations you will be able to perform:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// creating a person
Person person = new Person();
person.name = "Stef";
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1);
person.status = Status.Alive;

// persist it
person.persist();

// note that once persisted, you don't need to explicitly save your entity: all
// modifications are automatically persisted on transaction commit.

// check if it's persistent
if(person.isPersistent()){
    // delete it
    person.delete();
}

// getting a list of all Person entities
List&lt;Person&gt; allPersons = Person.listAll();

// finding a specific person by ID
person = Person.findById(personId);

// finding a specific person by ID via an Optional
Optional&lt;Person&gt; optional = Person.findByIdOptional(personId);
person = optional.orElseThrow(() -&gt; new NotFoundException());

// finding all living persons
List&lt;Person&gt; livingPersons = Person.list("status", Status.Alive);

// counting all persons
long countAll = Person.count();

// counting all living persons
long countAlive = Person.count("status", Status.Alive);

// delete all living persons
Person.delete("status", Status.Alive);

// delete all persons
Person.deleteAll();

// delete by id
boolean deleted = Person.deleteById(personId);

// set the name of all living persons to 'Mortal'
Person.update("name = 'Mortal' where status = ?1", Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>All <code>list</code> methods have equivalent <code>stream</code> versions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">try (Stream&lt;Person&gt; persons = Person.streamAll()) {
    List&lt;String&gt; namesButEmmanuels = persons
        .map(p -&gt; p.name.toLowerCase() )
        .filter( n -&gt; ! "emmanuel".equals(n) )
        .collect(Collectors.toList());
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The <code>stream</code> methods require a transaction to work.<br>
As they perform I/O operations, they should be closed via the <code>close()</code> method or via a try-with-resource to close the underlying <code>ResultSet</code>.
If not, you will see warnings from Agroal that will close the underlying <code>ResultSet</code> for you.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="adding-entity-methods"><a class="anchor" href="#adding-entity-methods"></a>Adding entity methods</h3>
<div class="paragraph">
<p>Add custom queries on your entities inside the entities themselves.
That way, you and your co-workers can find them easily, and queries are co-located with the object they operate on.
Adding them as static methods in your entity class is the Panache Active Record way.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person extends PanacheEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    public static Person findByName(String name){
        return find("name", name).firstResult();
    }

    public static List&lt;Person&gt; findAlive(){
        return list("status", Status.Alive);
    }

    public static void deleteStefs(){
        delete("name", "Stef");
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution-2-using-the-repository-pattern"><a class="anchor" href="#solution-2-using-the-repository-pattern"></a>Solution 2: using the repository pattern</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="defining-your-entity-2"><a class="anchor" href="#defining-your-entity-2"></a>Defining your entity</h3>
<div class="paragraph">
<p>When using the repository pattern, you can define your entities as regular JPA entities.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person {
    @Id @GeneratedValue private Long id;
    private String name;
    private LocalDate birth;
    private Status status;

    public Long getId(){
        return id;
    }
    public void setId(Long id){
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public LocalDate getBirth() {
        return birth;
    }
    public void setBirth(LocalDate birth) {
        this.birth = birth;
    }
    public Status getStatus() {
        return status;
    }
    public void setStatus(Status status) {
        this.status = status;
    }
}</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
If you don&#8217;t want to bother defining getters/setters for your entities, you can make them extend <code>PanacheEntityBase</code> and
Quarkus will generate them for you. You can even extend <code>PanacheEntity</code> and take advantage of the default ID it provides.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="defining-your-repository"><a class="anchor" href="#defining-your-repository"></a>Defining your repository</h3>
<div class="paragraph">
<p>When using Repositories, you get the exact same convenient methods as with the active record pattern, injected in your Repository,
by making them implements <code>PanacheRepository</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class PersonRepository implements PanacheRepository&lt;Person&gt; {

   // put your custom logic here as instance methods

   public Person findByName(String name){
       return find("name", name).firstResult();
   }

   public List&lt;Person&gt; findAlive(){
       return list("status", Status.Alive);
   }

   public void deleteStefs(){
       delete("name", "Stef");
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>All the operations that are defined on <code>PanacheEntityBase</code> are available on your repository, so using it
is exactly the same as using the active record pattern, except you need to inject it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Inject
PersonRepository personRepository;

@GET
public long count(){
    return personRepository.count();
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="most-useful-operations-2"><a class="anchor" href="#most-useful-operations-2"></a>Most useful operations</h3>
<div class="paragraph">
<p>Once you have written your repository, here are the most common operations you will be able to perform:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// creating a person
Person person = new Person();
person.name = "Stef";
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1);
person.status = Status.Alive;

// persist it
personRepository.persist(person);

// note that once persisted, you don't need to explicitly save your entity: all
// modifications are automatically persisted on transaction commit.

// check if it's persistent
if(personRepository.isPersistent(person)){
    // delete it
    personRepository.delete(person);
}

// getting a list of all Person entities
List&lt;Person&gt; allPersons = personRepository.listAll();

// finding a specific person by ID
person = personRepository.findById(personId);

// finding a specific person by ID via an Optional
Optional&lt;Person&gt; optional = personRepository.findByIdOptional(personId);
person = optional.orElseThrow(() -&gt; new NotFoundException());

// finding all living persons
List&lt;Person&gt; livingPersons = personRepository.list("status", Status.Alive);

// counting all persons
long countAll = personRepository.count();

// counting all living persons
long countAlive = personRepository.count("status", Status.Alive);

// delete all living persons
personRepository.delete("status", Status.Alive);

// delete all persons
personRepository.deleteAll();

// delete by id
boolean deleted = personRepository.deleteById(personId);

// set the name of all living persons to 'Mortal'
personRepository.update("name = 'Mortal' where status = ?1", Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>All <code>list</code> methods have equivalent <code>stream</code> versions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Stream&lt;Person&gt; persons = personRepository.streamAll();
List&lt;String&gt; namesButEmmanuels = persons
    .map(p -&gt; p.name.toLowerCase() )
    .filter( n -&gt; ! "emmanuel".equals(n) )
    .collect(Collectors.toList());</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The <code>stream</code> methods require a transaction to work.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The rest of the documentation show usages based on the active record pattern only,
but keep in mind that they can be performed with the repository pattern as well.
The repository pattern examples have been omitted for brevity.
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="advanced-query"><a class="anchor" href="#advanced-query"></a>Advanced Query</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="paging"><a class="anchor" href="#paging"></a>Paging</h3>
<div class="paragraph">
<p>You should only use <code>list</code> and <code>stream</code> methods if your table contains small enough data sets. For larger data
sets you can use the <code>find</code> method equivalents, which return a <code>PanacheQuery</code> on which you can do paging:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// create a query for all living persons
PanacheQuery&lt;Person&gt; livingPersons = Person.find("status", Status.Alive);

// make it use pages of 25 entries at a time
livingPersons.page(Page.ofSize(25));

// get the first page
List&lt;Person&gt; firstPage = livingPersons.list();

// get the second page
List&lt;Person&gt; secondPage = livingPersons.nextPage().list();

// get page 7
List&lt;Person&gt; page7 = livingPersons.page(Page.of(7, 25)).list();

// get the number of pages
int numberOfPages = livingPersons.pageCount();

// get the total number of entities returned by this query without paging
long count = livingPersons.count();

// and you can chain methods of course
return Person.find("status", Status.Alive)
    .page(Page.ofSize(25))
    .nextPage()
    .stream()</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>PanacheQuery</code> type has many other methods to deal with paging and returning streams.</p>
</div>
</div>
<div class="sect2">
<h3 id="using-a-range-instead-of-pages"><a class="anchor" href="#using-a-range-instead-of-pages"></a>Using a range instead of pages</h3>
<div class="paragraph">
<p><code>PanacheQuery</code> also allows range-based queries.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// create a query for all living persons
PanacheQuery&lt;Person&gt; livingPersons = Person.find("status", Status.Alive);

// make it use a range: start at index 0 until index 24 (inclusive).
livingPersons.range(0, 24);

// get the range
List&lt;Person&gt; firstRange = livingPersons.list();

// to get the next range, you need to call range again
List&lt;Person&gt; secondRange = livingPersons.range(25, 49).list();</code></pre>
</div>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You cannot mix ranges and pages: if you use a range, all methods that depend on having a current page will throw an <code>UnsupportedOperationException</code>;
you can switch back to paging using <code>page(Page)</code> or <code>page(int, int)</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="sorting"><a class="anchor" href="#sorting"></a>Sorting</h3>
<div class="paragraph">
<p>All methods accepting a query string also accept the following simplified query form:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">List&lt;Person&gt; persons = Person.list("order by name,birth");</code></pre>
</div>
</div>
<div class="paragraph">
<p>But these methods also accept an optional <code>Sort</code> parameter, which allows your to abstract your sorting:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">List&lt;Person&gt; persons = Person.list(Sort.by("name").and("birth"));

// and with more restrictions
List&lt;Person&gt; persons = Person.list("status", Sort.by("name").and("birth"), Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>Sort</code> class has plenty of methods for adding columns and specifying sort direction.</p>
</div>
</div>
<div class="sect2">
<h3 id="simplified-queries"><a class="anchor" href="#simplified-queries"></a>Simplified queries</h3>
<div class="paragraph">
<p>Normally, HQL queries are of this form: <code>from EntityName [where &#8230;&#8203;] [order by &#8230;&#8203;]</code>, with optional elements
at the end.</p>
</div>
<div class="paragraph">
<p>If your select query does not start with <code>from</code>, we support the following additional forms:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>order by &#8230;&#8203;</code> which will expand to <code>from EntityName order by &#8230;&#8203;</code></p>
</li>
<li>
<p><code>&lt;singleColumnName&gt;</code> (and single parameter) which will expand to <code>from EntityName where &lt;singleColumnName&gt; = ?</code></p>
</li>
<li>
<p><code>&lt;query&gt;</code> will expand to <code>from EntityName where &lt;query&gt;</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If your update query does not start with <code>update</code>, we support the following additional forms:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>from EntityName &#8230;&#8203;</code> which will expand to <code>update from EntityName &#8230;&#8203;</code></p>
</li>
<li>
<p><code>set? &lt;singleColumnName&gt;</code> (and single parameter) which will expand to <code>update from EntityName set &lt;singleColumnName&gt; = ?</code></p>
</li>
<li>
<p><code>set? &lt;update-query&gt;</code> will expand to <code>update from EntityName set &lt;update-query&gt;</code></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
You can also write your queries in plain
<a href="https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#hql">HQL</a>:
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Order.find("select distinct o from Order o left join fetch o.lineItems");
Order.update("update from Person set name = 'Mortal' where status = ?", Status.Alive);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="named-queries"><a class="anchor" href="#named-queries"></a>Named queries</h3>
<div class="paragraph">
<p>You can reference a named query instead of a (simplified) HQL query by prefixing its name with the '#' character.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
@NamedQuery(name = "Person.getByName", query = "from Person where name = :name")
public class Person extends PanacheEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    public static Person findByName(String name){
        return find("#Person.getByName", name).firstResult();
    }
}</code></pre>
</div>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Named queries can only be defined inside your JPA entity classes (being the Panache entity class, or the repository parameterized type),
or on one of its super classes.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="query-parameters"><a class="anchor" href="#query-parameters"></a>Query parameters</h3>
<div class="paragraph">
<p>You can pass query parameters by index (1-based) as shown below:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Person.find("name = ?1 and status = ?2", "stef", Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or by name using a <code>Map</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
params.put("name", "stef");
params.put("status", Status.Alive);
Person.find("name = :name and status = :status", params);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or using the convenience class <code>Parameters</code> either as is or to build a <code>Map</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// generate a Map
Person.find("name = :name and status = :status",
         Parameters.with("name", "stef").and("status", Status.Alive).map());

// use it as-is
Person.find("name = :name and status = :status",
         Parameters.with("name", "stef").and("status", Status.Alive));</code></pre>
</div>
</div>
<div class="paragraph">
<p>Every query operation accepts passing parameters by index (<code>Object&#8230;&#8203;</code>), or by name (<code>Map&lt;String,Object&gt;</code> or <code>Parameters</code>).</p>
</div>
</div>
<div class="sect2">
<h3 id="query-projection"><a class="anchor" href="#query-projection"></a>Query projection</h3>
<div class="paragraph">
<p>Query projection can be done with the <code>project(Class)</code> method on the <code>PanacheQuery</code> object that is returned by the <code>find()</code> methods.</p>
</div>
<div class="paragraph">
<p>You can use it to restrict which fields will be returned by the database.</p>
</div>
<div class="paragraph">
<p>Hibernate will use <strong>DTO projection</strong> and generate a SELECT clause with the attributes from the projection class.
This is also called <strong>dynamic instantiation</strong> or <strong>constructor expression</strong>, more info can be found on the Hibernate guide:
<a href="https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#hql-select-clause">hql select clause</a></p>
</div>
<div class="paragraph">
<p>The projection class needs to be a valid Java Bean and have a constructor that contains all its attributes, this constructor will be used to
instantiate the projection DTO instead of using the entity class. This must be the only constructor of the class.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import io.quarkus.runtime.annotations.RegisterForReflection;

@RegisterForReflection <i class="conum" data-value="1"></i><b>(1)</b>
public class PersonName {
    public final String name; <i class="conum" data-value="2"></i><b>(2)</b>

    public PersonName(String name){ <i class="conum" data-value="3"></i><b>(3)</b>
        this.name = name;
    }
}

// only 'name' will be loaded from the database
PanacheQuery&lt;PersonName&gt; query = Person.find("status", Status.Alive).project(PersonName.class);</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>If you plan to deploy your application as a native executable, you must register manually the projection class for reflection.</p>
</li>
<li>
<p>We use public fields here, but you can use private fields and getters/setters if you prefer.</p>
</li>
<li>
<p>This constructor will be used by Hibernate, it must be the only constructor in your class and have all the class attributes as parameters.</p>
</li>
</ol>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The implementation of the <code>project(Class)</code> method uses the constructor&#8217;s parameter names to build the select clause of the query,
so the compiler must be configured to store parameter names inside the compiled class.
This is enabled by default if you are using the Quarkus Maven archetype. If you are not using it, add the property <code>&lt;maven.compiler.parameters&gt;true&lt;/maven.compiler.parameters&gt;</code> to your pom.xml.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="transactions"><a class="anchor" href="#transactions"></a>Transactions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Make sure to wrap methods modifying your database (e.g. <code>entity.persist()</code>) within a transaction. Marking a
CDI bean method <code>@Transactional</code> will do that for you and make that method a transaction boundary. We recommend doing
so at your application entry point boundaries like your REST endpoint controllers.</p>
</div>
<div class="paragraph">
<p>JPA batches changes you make to your entities and sends changes (it&#8217;s called flush) at the end of the transaction or before a query.
This is usually a good thing as it&#8217;s more efficient.
But if you want to check optimistic locking failures, do object validation right away or generally want to get immediate feedback, you can force the flush operation by calling <code>entity.flush()</code> or even use <code>entity.persistAndFlush()</code> to make it a single method call. This will allow you to catch any <code>PersistenceException</code> that could occur when JPA send those changes to the database.
Remember, this is less efficient so don&#8217;t abuse it.
And your transaction still has to be committed.</p>
</div>
<div class="paragraph">
<p>Here is an example of the usage of the flush method to allow making a specific action in case of <code>PersistenceException</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Transactional
public void create(Parameter parameter){
    try {
        //Here I use the persistAndFlush() shorthand method on a Panache repository to persist to database then flush the changes.
        return parameterRepository.persistAndFlush(parameter);
    }
    catch(PersistenceException pe){
        LOG.error("Unable to create the parameter", pe);
        //in case of error, I save it to disk
        diskPersister.save(parameter);
    }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="lock-management"><a class="anchor" href="#lock-management"></a>Lock management</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Panache provides direct support for database locking with your entity/repository, using <code>findById(Object, LockModeType)</code> or <code>find().withLock(LockModeType)</code>.</p>
</div>
<div class="paragraph">
<p>The following examples are for the active record pattern, but the same can be used with repositories.</p>
</div>
<div class="sect2">
<h3 id="first-locking-using-findbyid"><a class="anchor" href="#first-locking-using-findbyid"></a>First: Locking using findById().</h3>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class PersonEndpoint {

    @GET
    @Transactional
    public Person findByIdForUpdate(Long id){
        Person p = Person.findById(id, LockModeType.PESSIMISTIC_WRITE);
        //do something useful, the lock will be released when the transaction ends.
        return person;
    }

}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="second-locking-in-a-find"><a class="anchor" href="#second-locking-in-a-find"></a>Second: Locking in a find().</h3>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class PersonEndpoint {

    @GET
    @Transactional
    public Person findByNameForUpdate(String name){
        Person p = Person.find("name", name).withLock(LockModeType.PESSIMISTIC_WRITE).findOne();
        //do something useful, the lock will be released when the transaction ends.
        return person;
    }

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Be careful that locks are released when the transaction ends, so the method that invokes the lock query must be annotated with the <code>@Transactional</code> annotation.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="custom-ids"><a class="anchor" href="#custom-ids"></a>Custom IDs</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IDs are often a touchy subject, and not everyone&#8217;s up for letting them handled by the framework, once again we
have you covered.</p>
</div>
<div class="paragraph">
<p>You can specify your own ID strategy by extending <code>PanacheEntityBase</code> instead of <code>PanacheEntity</code>. Then
you just declare whatever ID you want as a public field:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person extends PanacheEntityBase {

    @Id
    @SequenceGenerator(
            name = "personSequence",
            sequenceName = "person_id_seq",
            allocationSize = 1,
            initialValue = 4)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "personSequence")
    public Integer id;

    //...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you&#8217;re using repositories, then you will want to extend <code>PanacheRepositoryBase</code> instead of <code>PanacheRepository</code>
and specify your ID type as an extra type parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class PersonRepository implements PanacheRepositoryBase&lt;Person,Integer&gt; {
    //...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mocking"><a class="anchor" href="#mocking"></a>Mocking</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="using-the-active-record-pattern"><a class="anchor" href="#using-the-active-record-pattern"></a>Using the active record pattern</h3>
<div class="paragraph">
<p>If you are using the active record pattern you cannot use Mockito directly as it does not support mocking static methods,
but you can use the <code>quarkus-panache-mock</code> module which allows you to use Mockito to mock all provided static
methods, including your own.</p>
</div>
<div class="paragraph">
<p>Add this dependency to your <code>pom.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-panache-mock&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Given this simple entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person extends PanacheEntity {

    public String name;

    public static List&lt;Person&gt; findOrdered() {
        return find("ORDER BY name").list();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can write your mocking test like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@QuarkusTest
public class PanacheFunctionalityTest {

    @Test
    public void testPanacheMocking() {
        PanacheMock.mock(Person.class);

        // Mocked classes always return a default value
        Assertions.assertEquals(0, Person.count());

        // Now let's specify the return value
        Mockito.when(Person.count()).thenReturn(23l);
        Assertions.assertEquals(23, Person.count());

        // Now let's change the return value
        Mockito.when(Person.count()).thenReturn(42l);
        Assertions.assertEquals(42, Person.count());

        // Now let's call the original method
        Mockito.when(Person.count()).thenCallRealMethod();
        Assertions.assertEquals(0, Person.count());

        // Check that we called it 4 times
        PanacheMock.verify(Person.class, Mockito.times(4)).count();<i class="conum" data-value="1"></i><b>(1)</b>

        // Mock only with specific parameters
        Person p = new Person();
        Mockito.when(Person.findById(12l)).thenReturn(p);
        Assertions.assertSame(p, Person.findById(12l));
        Assertions.assertNull(Person.findById(42l));

        // Mock throwing
        Mockito.when(Person.findById(12l)).thenThrow(new WebApplicationException());
        Assertions.assertThrows(WebApplicationException.class, () -&gt; Person.findById(12l));

        // We can even mock your custom methods
        Mockito.when(Person.findOrdered()).thenReturn(Collections.emptyList());
        Assertions.assertTrue(Person.findOrdered().isEmpty());

        // Mocking a void method
        Person.voidMethod();

        // Make it throw
        PanacheMock.doThrow(new RuntimeException("Stef2")).when(Person.class).voidMethod();
        try {
            Person.voidMethod();
            Assertions.fail();
        } catch (RuntimeException x) {
            Assertions.assertEquals("Stef2", x.getMessage());
        }

        // Back to doNothing
        PanacheMock.doNothing().when(Person.class).voidMethod();
        Person.voidMethod();

        // Make it call the real method
        PanacheMock.doCallRealMethod().when(Person.class).voidMethod();
        try {
            Person.voidMethod();
            Assertions.fail();
        } catch (RuntimeException x) {
            Assertions.assertEquals("void", x.getMessage());
        }

        PanacheMock.verify(Person.class).findOrdered();
        PanacheMock.verify(Person.class, Mockito.atLeast(4)).voidMethod();
        PanacheMock.verify(Person.class, Mockito.atLeastOnce()).findById(Mockito.any());
        PanacheMock.verifyNoMoreInteractions(Person.class);
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Be sure to call your <code>verify</code> and <code>do*</code> methods on <code>PanacheMock</code> rather than <code>Mockito</code>, otherwise you won&#8217;t know
what mock object to pass.</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="using-the-repository-pattern"><a class="anchor" href="#using-the-repository-pattern"></a>Using the repository pattern</h3>
<div class="paragraph">
<p>If you are using the repository pattern you can use Mockito directly, using the <code>quarkus-junit5-mockito</code> module,
which makes mocking beans much easier:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-junit5-mockito&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Given this simple entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Person {

    @Id
    @GeneratedValue
    public Long id;

    public String name;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And this repository:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class PersonRepository implements PanacheRepository&lt;Person&gt; {
    public List&lt;Person&gt; findOrdered() {
        return find("ORDER BY name").list();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can write your mocking test like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@QuarkusTest
public class PanacheFunctionalityTest {
    @InjectMock
    PersonRepository personRepository;

    @Test
    public void testPanacheRepositoryMocking() throws Throwable {
        // Mocked classes always return a default value
        Assertions.assertEquals(0, personRepository.count());

        // Now let's specify the return value
        Mockito.when(personRepository.count()).thenReturn(23l);
        Assertions.assertEquals(23, personRepository.count());

        // Now let's change the return value
        Mockito.when(personRepository.count()).thenReturn(42l);
        Assertions.assertEquals(42, personRepository.count());

        // Now let's call the original method
        Mockito.when(personRepository.count()).thenCallRealMethod();
        Assertions.assertEquals(0, personRepository.count());

        // Check that we called it 4 times
        Mockito.verify(personRepository, Mockito.times(4)).count();

        // Mock only with specific parameters
        Person p = new Person();
        Mockito.when(personRepository.findById(12l)).thenReturn(p);
        Assertions.assertSame(p, personRepository.findById(12l));
        Assertions.assertNull(personRepository.findById(42l));

        // Mock throwing
        Mockito.when(personRepository.findById(12l)).thenThrow(new WebApplicationException());
        Assertions.assertThrows(WebApplicationException.class, () -&gt; personRepository.findById(12l));

        Mockito.when(personRepository.findOrdered()).thenReturn(Collections.emptyList());
        Assertions.assertTrue(personRepository.findOrdered().isEmpty());

        // We can even mock your custom methods
        Mockito.verify(personRepository).findOrdered();
        Mockito.verify(personRepository, Mockito.atLeastOnce()).findById(Mockito.any());
        Mockito.verifyNoMoreInteractions(personRepository);
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="how-and-why-we-simplify-hibernate-orm-mappings"><a class="anchor" href="#how-and-why-we-simplify-hibernate-orm-mappings"></a>How and why we simplify Hibernate ORM mappings</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When it comes to writing Hibernate ORM entities, there are a number of annoying things that users have grown used to
reluctantly deal with, such as:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Duplicating ID logic: most entities need an ID, most people don&#8217;t care how it&#8217;s set, because it&#8217;s not really
relevant to your model.</p>
</li>
<li>
<p>Dumb getters and setters: since Java lacks support for properties in the language, we have to create fields,
then generate getters and setters for those fields, even if they don&#8217;t actually do anything more than read/write
the fields.</p>
</li>
<li>
<p>Traditional EE patterns advise to split entity definition (the model) from the operations you can do on them
(DAOs, Repositories), but really that requires an unnatural split between the state and its operations even though
we would never do something like that for regular objects in the Object Oriented architecture, where state and methods
are in the same class. Moreover, this requires two classes per entity, and requires injection of the DAO or Repository
where you need to do entity operations, which breaks your edit flow and requires you to get out of the code you&#8217;re
writing to set up an injection point before coming back to use it.</p>
</li>
<li>
<p>Hibernate queries are super powerful, but overly verbose for common operations, requiring you to write queries even
when you don&#8217;t need all the parts.</p>
</li>
<li>
<p>Hibernate is very general-purpose, but does not make it trivial to do trivial operations that make up 90% of our
model usage.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>With Panache, we took an opinionated approach to tackle all these problems:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Make your entities extend <code>PanacheEntity</code>: it has an ID field that is auto-generated. If you require
a custom ID strategy, you can extend <code>PanacheEntityBase</code> instead and handle the ID yourself.</p>
</li>
<li>
<p>Use public fields. Get rid of dumb getter and setters. Under the hood, we will generate all getters and setters
that are missing, and rewrite every access to these fields to use the accessor methods. This way you can still
write <em>useful</em> accessors when you need them, which will be used even though your entity users still use field accesses.</p>
</li>
<li>
<p>With the active record pattern: put all your entity logic in static methods in your entity class and don&#8217;t create DAOs.
Your entity superclass comes with lots of super useful static methods, and you can add your own in your entity class.
Users can just start using your entity <code>Person</code> by typing <code>Person.</code> and getting completion for all the operations in a single place.</p>
</li>
<li>
<p>Don&#8217;t write parts of the query that you don&#8217;t need: write <code>Person.find("order by name")</code> or
<code>Person.find("name = ?1 and status = ?2", "stef", Status.Alive)</code> or even better
<code>Person.find("name", "stef")</code>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>That&#8217;s all there is to it: with Panache, Hibernate ORM has never looked so trim and neat.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="defining-entities-in-external-projects-or-jars"><a class="anchor" href="#defining-entities-in-external-projects-or-jars"></a>Defining entities in external projects or jars</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Hibernate ORM with Panache relies on compile-time bytecode enhancements to your entities.</p>
</div>
<div class="paragraph">
<p>It attempts to identity archives with Panache entities (and consumers of Panache entities)
by the presence of the marker file <code>META-INF/panache-archive.marker</code>. Panache includes an
annotation processor that will automatically create this file in archives that depend on
Panache (even indirectly). If you have disabled annotation processors you may need to create
this file manually in some cases.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
If you include the jpa-modelgen annotation processor this will exclude the Panache
annotation processor by default. If you do this you should either create the marker file
yourself, or add the <code>quarkus-panache-common</code> as well, as shown below:
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;plugin&gt;
    &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
    &lt;version&gt;${compiler-plugin.version}&lt;/version&gt;
    &lt;configuration&gt;
      &lt;annotationProcessorPaths&gt;
        &lt;annotationProcessorPath&gt;
          &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
          &lt;artifactId&gt;hibernate-jpamodelgen&lt;/artifactId&gt;
          &lt;version&gt;${hibernate.version}&lt;/version&gt;
        &lt;/annotationProcessorPath&gt;
        &lt;annotationProcessorPath&gt;
          &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
          &lt;artifactId&gt;quarkus-panache-common&lt;/artifactId&gt;
          &lt;version&gt;${quarkus.platform.version}&lt;/version&gt;
        &lt;/annotationProcessorPath&gt;
      &lt;/annotationProcessorPaths&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
